home *** CD-ROM | disk | FTP | other *** search
/ Clickx 96 / Clickx 96.iso / software / tools / tool / xbmc-10.1.exe / addons / script.module.pil / lib / PIL / TiffImagePlugin.py < prev    next >
Encoding:
Python Source  |  2009-04-06  |  27.4 KB  |  861 lines

  1. #
  2. # The Python Imaging Library.
  3. # $Id$
  4. #
  5. # TIFF file handling
  6. #
  7. # TIFF is a flexible, if somewhat aged, image file format originally
  8. # defined by Aldus.  Although TIFF supports a wide variety of pixel
  9. # layouts and compression methods, the name doesn't really stand for
  10. # "thousands of incompatible file formats," it just feels that way.
  11. #
  12. # To read TIFF data from a stream, the stream must be seekable.  For
  13. # progressive decoding, make sure to use TIFF files where the tag
  14. # directory is placed first in the file.
  15. #
  16. # History:
  17. # 1995-09-01 fl   Created
  18. # 1996-05-04 fl   Handle JPEGTABLES tag
  19. # 1996-05-18 fl   Fixed COLORMAP support
  20. # 1997-01-05 fl   Fixed PREDICTOR support
  21. # 1997-08-27 fl   Added support for rational tags (from Perry Stoll)
  22. # 1998-01-10 fl   Fixed seek/tell (from Jan Blom)
  23. # 1998-07-15 fl   Use private names for internal variables
  24. # 1999-06-13 fl   Rewritten for PIL 1.0 (1.0)
  25. # 2000-10-11 fl   Additional fixes for Python 2.0 (1.1)
  26. # 2001-04-17 fl   Fixed rewind support (seek to frame 0) (1.2)
  27. # 2001-05-12 fl   Added write support for more tags (from Greg Couch) (1.3)
  28. # 2001-12-18 fl   Added workaround for broken Matrox library
  29. # 2002-01-18 fl   Don't mess up if photometric tag is missing (D. Alan Stewart)
  30. # 2003-05-19 fl   Check FILLORDER tag
  31. # 2003-09-26 fl   Added RGBa support
  32. # 2004-02-24 fl   Added DPI support; fixed rational write support
  33. # 2005-02-07 fl   Added workaround for broken Corel Draw 10 files
  34. # 2006-01-09 fl   Added support for float/double tags (from Russell Nelson)
  35. #
  36. # Copyright (c) 1997-2006 by Secret Labs AB.  All rights reserved.
  37. # Copyright (c) 1995-1997 by Fredrik Lundh
  38. #
  39. # See the README file for information on usage and redistribution.
  40. #
  41.  
  42. __version__ = "1.3.5"
  43.  
  44. import Image, ImageFile
  45. import ImagePalette
  46.  
  47. import array, string, sys
  48.  
  49. II = "II" # little-endian (intel-style)
  50. MM = "MM" # big-endian (motorola-style)
  51.  
  52. try:
  53.     if sys.byteorder == "little":
  54.         native_prefix = II
  55.     else:
  56.         native_prefix = MM
  57. except AttributeError:
  58.     if ord(array.array("i",[1]).tostring()[0]):
  59.         native_prefix = II
  60.     else:
  61.         native_prefix = MM
  62.  
  63. #
  64. # --------------------------------------------------------------------
  65. # Read TIFF files
  66.  
  67. def il16(c,o=0):
  68.     return ord(c[o]) + (ord(c[o+1])<<8)
  69. def il32(c,o=0):
  70.     return ord(c[o]) + (ord(c[o+1])<<8) + (ord(c[o+2])<<16) + (ord(c[o+3])<<24)
  71. def ol16(i):
  72.     return chr(i&255) + chr(i>>8&255)
  73. def ol32(i):
  74.     return chr(i&255) + chr(i>>8&255) + chr(i>>16&255) + chr(i>>24&255)
  75.  
  76. def ib16(c,o=0):
  77.     return ord(c[o+1]) + (ord(c[o])<<8)
  78. def ib32(c,o=0):
  79.     return ord(c[o+3]) + (ord(c[o+2])<<8) + (ord(c[o+1])<<16) + (ord(c[o])<<24)
  80. def ob16(i):
  81.     return chr(i>>8&255) + chr(i&255)
  82. def ob32(i):
  83.     return chr(i>>24&255) + chr(i>>16&255) + chr(i>>8&255) + chr(i&255)
  84.  
  85. # a few tag names, just to make the code below a bit more readable
  86. IMAGEWIDTH = 256
  87. IMAGELENGTH = 257
  88. BITSPERSAMPLE = 258
  89. COMPRESSION = 259
  90. PHOTOMETRIC_INTERPRETATION = 262
  91. FILLORDER = 266
  92. IMAGEDESCRIPTION = 270
  93. STRIPOFFSETS = 273
  94. SAMPLESPERPIXEL = 277
  95. ROWSPERSTRIP = 278
  96. STRIPBYTECOUNTS = 279
  97. X_RESOLUTION = 282
  98. Y_RESOLUTION = 283
  99. PLANAR_CONFIGURATION = 284
  100. RESOLUTION_UNIT = 296
  101. SOFTWARE = 305
  102. DATE_TIME = 306
  103. ARTIST = 315
  104. PREDICTOR = 317
  105. COLORMAP = 320
  106. TILEOFFSETS = 324
  107. EXTRASAMPLES = 338
  108. SAMPLEFORMAT = 339
  109. JPEGTABLES = 347
  110. COPYRIGHT = 33432
  111. IPTC_NAA_CHUNK = 33723 # newsphoto properties
  112. PHOTOSHOP_CHUNK = 34377 # photoshop properties
  113. ICCPROFILE = 34675
  114. EXIFIFD = 34665
  115. XMP = 700
  116.  
  117. COMPRESSION_INFO = {
  118.     # Compression => pil compression name
  119.     1: "raw",
  120.     2: "tiff_ccitt",
  121.     3: "group3",
  122.     4: "group4",
  123.     5: "tiff_lzw",
  124.     6: "tiff_jpeg", # obsolete
  125.     7: "jpeg",
  126.     32771: "tiff_raw_16", # 16-bit padding
  127.     32773: "packbits"
  128. }
  129.  
  130. OPEN_INFO = {
  131.     # (ByteOrder, PhotoInterpretation, SampleFormat, FillOrder, BitsPerSample,
  132.     #  ExtraSamples) => mode, rawmode
  133.     (II, 0, 1, 1, (1,), ()): ("1", "1;I"),
  134.     (II, 0, 1, 2, (1,), ()): ("1", "1;IR"),
  135.     (II, 0, 1, 1, (8,), ()): ("L", "L;I"),
  136.     (II, 0, 1, 2, (8,), ()): ("L", "L;IR"),
  137.     (II, 1, 1, 1, (1,), ()): ("1", "1"),
  138.     (II, 1, 1, 2, (1,), ()): ("1", "1;R"),
  139.     (II, 1, 1, 1, (8,), ()): ("L", "L"),
  140.     (II, 1, 1, 1, (8,8), (2,)): ("LA", "LA"),
  141.     (II, 1, 1, 2, (8,), ()): ("L", "L;R"),
  142.     (II, 1, 1, 1, (16,), ()): ("I;16", "I;16"),
  143.     (II, 1, 2, 1, (16,), ()): ("I;16S", "I;16S"),
  144.     (II, 1, 2, 1, (32,), ()): ("I", "I;32S"),
  145.     (II, 1, 3, 1, (32,), ()): ("F", "F;32F"),
  146.     (II, 2, 1, 1, (8,8,8), ()): ("RGB", "RGB"),
  147.     (II, 2, 1, 2, (8,8,8), ()): ("RGB", "RGB;R"),
  148.     (II, 2, 1, 1, (8,8,8,8), (0,)): ("RGBX", "RGBX"),
  149.     (II, 2, 1, 1, (8,8,8,8), (1,)): ("RGBA", "RGBa"),
  150.     (II, 2, 1, 1, (8,8,8,8), (2,)): ("RGBA", "RGBA"),
  151.     (II, 2, 1, 1, (8,8,8,8), (999,)): ("RGBA", "RGBA"), # corel draw 10
  152.     (II, 3, 1, 1, (1,), ()): ("P", "P;1"),
  153.     (II, 3, 1, 2, (1,), ()): ("P", "P;1R"),
  154.     (II, 3, 1, 1, (2,), ()): ("P", "P;2"),
  155.     (II, 3, 1, 2, (2,), ()): ("P", "P;2R"),
  156.     (II, 3, 1, 1, (4,), ()): ("P", "P;4"),
  157.     (II, 3, 1, 2, (4,), ()): ("P", "P;4R"),
  158.     (II, 3, 1, 1, (8,), ()): ("P", "P"),
  159.     (II, 3, 1, 1, (8,8), (2,)): ("PA", "PA"),
  160.     (II, 3, 1, 2, (8,), ()): ("P", "P;R"),
  161.     (II, 5, 1, 1, (8,8,8,8), ()): ("CMYK", "CMYK"),
  162.     (II, 6, 1, 1, (8,8,8), ()): ("YCbCr", "YCbCr"),
  163.     (II, 8, 1, 1, (8,8,8), ()): ("LAB", "LAB"),
  164.  
  165.     (MM, 0, 1, 1, (1,), ()): ("1", "1;I"),
  166.     (MM, 0, 1, 2, (1,), ()): ("1", "1;IR"),
  167.     (MM, 0, 1, 1, (8,), ()): ("L", "L;I"),
  168.     (MM, 0, 1, 2, (8,), ()): ("L", "L;IR"),
  169.     (MM, 1, 1, 1, (1,), ()): ("1", "1"),
  170.     (MM, 1, 1, 2, (1,), ()): ("1", "1;R"),
  171.     (MM, 1, 1, 1, (8,), ()): ("L", "L"),
  172.     (MM, 1, 1, 1, (8,8), (2,)): ("LA", "LA"),
  173.     (MM, 1, 1, 2, (8,), ()): ("L", "L;R"),
  174.     (MM, 1, 1, 1, (16,), ()): ("I;16B", "I;16B"),
  175.     (MM, 1, 2, 1, (16,), ()): ("I;16BS", "I;16BS"),
  176.     (MM, 1, 2, 1, (32,), ()): ("I;32BS", "I;32BS"),
  177.     (MM, 1, 3, 1, (32,), ()): ("F;32BF", "F;32BF"),
  178.     (MM, 2, 1, 1, (8,8,8), ()): ("RGB", "RGB"),
  179.     (MM, 2, 1, 2, (8,8,8), ()): ("RGB", "RGB;R"),
  180.     (MM, 2, 1, 1, (8,8,8,8), (0,)): ("RGBX", "RGBX"),
  181.     (MM, 2, 1, 1, (8,8,8,8), (1,)): ("RGBA", "RGBa"),
  182.     (MM, 2, 1, 1, (8,8,8,8), (2,)): ("RGBA", "RGBA"),
  183.     (MM, 2, 1, 1, (8,8,8,8), (999,)): ("RGBA", "RGBA"), # corel draw 10
  184.     (MM, 3, 1, 1, (1,), ()): ("P", "P;1"),
  185.     (MM, 3, 1, 2, (1,), ()): ("P", "P;1R"),
  186.     (MM, 3, 1, 1, (2,), ()): ("P", "P;2"),
  187.     (MM, 3, 1, 2, (2,), ()): ("P", "P;2R"),
  188.     (MM, 3, 1, 1, (4,), ()): ("P", "P;4"),
  189.     (MM, 3, 1, 2, (4,), ()): ("P", "P;4R"),
  190.     (MM, 3, 1, 1, (8,), ()): ("P", "P"),
  191.     (MM, 3, 1, 1, (8,8), (2,)): ("PA", "PA"),
  192.     (MM, 3, 1, 2, (8,), ()): ("P", "P;R"),
  193.     (MM, 5, 1, 1, (8,8,8,8), ()): ("CMYK", "CMYK"),
  194.     (MM, 6, 1, 1, (8,8,8), ()): ("YCbCr", "YCbCr"),
  195.     (MM, 8, 1, 1, (8,8,8), ()): ("LAB", "LAB"),
  196.  
  197. }
  198.  
  199. PREFIXES = ["MM\000\052", "II\052\000", "II\xBC\000"]
  200.  
  201. def _accept(prefix):
  202.     return prefix[:4] in PREFIXES
  203.  
  204. ##
  205. # Wrapper for TIFF IFDs.
  206.  
  207. class ImageFileDirectory:
  208.  
  209.     # represents a TIFF tag directory.  to speed things up,
  210.     # we don't decode tags unless they're asked for.
  211.  
  212.     def __init__(self, prefix):
  213.         self.prefix = prefix[:2]
  214.         if self.prefix == MM:
  215.             self.i16, self.i32 = ib16, ib32
  216.             self.o16, self.o32 = ob16, ob32
  217.         elif self.prefix == II:
  218.             self.i16, self.i32 = il16, il32
  219.             self.o16, self.o32 = ol16, ol32
  220.         else:
  221.             raise SyntaxError("not a TIFF IFD")
  222.         self.reset()
  223.  
  224.     def reset(self):
  225.         self.tags = {}
  226.         self.tagdata = {}
  227.         self.tagtype = {} # added 2008-06-05 by Florian Hoech
  228.         self.next = None
  229.  
  230.     # dictionary API (sort of)
  231.  
  232.     def keys(self):
  233.         return self.tagdata.keys() + self.tags.keys()
  234.  
  235.     def items(self):
  236.         items = self.tags.items()
  237.         for tag in self.tagdata.keys():
  238.             items.append((tag, self[tag]))
  239.         return items
  240.  
  241.     def __len__(self):
  242.         return len(self.tagdata) + len(self.tags)
  243.  
  244.     def __getitem__(self, tag):
  245.         try:
  246.             return self.tags[tag]
  247.         except KeyError:
  248.             type, data = self.tagdata[tag] # unpack on the fly
  249.             size, handler = self.load_dispatch[type]
  250.             self.tags[tag] = data = handler(self, data)
  251.             del self.tagdata[tag]
  252.             return data
  253.  
  254.     def get(self, tag, default=None):
  255.         try:
  256.             return self[tag]
  257.         except KeyError:
  258.             return default
  259.  
  260.     def getscalar(self, tag, default=None):
  261.         try:
  262.             value = self[tag]
  263.             if len(value) != 1:
  264.                 if tag == SAMPLEFORMAT:
  265.                     # work around broken (?) matrox library
  266.                     # (from Ted Wright, via Bob Klimek)
  267.                     raise KeyError # use default
  268.                 raise ValueError, "not a scalar"
  269.             return value[0]
  270.         except KeyError:
  271.             if default is None:
  272.                 raise
  273.             return default
  274.  
  275.     def has_key(self, tag):
  276.         return self.tags.has_key(tag) or self.tagdata.has_key(tag)
  277.  
  278.     def __setitem__(self, tag, value):
  279.         if type(value) is not type(()):
  280.             value = (value,)
  281.         self.tags[tag] = value
  282.  
  283.     # load primitives
  284.  
  285.     load_dispatch = {}
  286.  
  287.     def load_byte(self, data):
  288.         l = []
  289.         for i in range(len(data)):
  290.             l.append(ord(data[i]))
  291.         return tuple(l)
  292.     load_dispatch[1] = (1, load_byte)
  293.  
  294.     def load_string(self, data):
  295.         if data[-1:] == '\0':
  296.             data = data[:-1]
  297.         return data
  298.     load_dispatch[2] = (1, load_string)
  299.  
  300.     def load_short(self, data):
  301.         l = []
  302.         for i in range(0, len(data), 2):
  303.             l.append(self.i16(data, i))
  304.         return tuple(l)
  305.     load_dispatch[3] = (2, load_short)
  306.  
  307.     def load_long(self, data):
  308.         l = []
  309.         for i in range(0, len(data), 4):
  310.             l.append(self.i32(data, i))
  311.         return tuple(l)
  312.     load_dispatch[4] = (4, load_long)
  313.  
  314.     def load_rational(self, data):
  315.         l = []
  316.         for i in range(0, len(data), 8):
  317.             l.append((self.i32(data, i), self.i32(data, i+4)))
  318.         return tuple(l)
  319.     load_dispatch[5] = (8, load_rational)
  320.  
  321.     def load_float(self, data):
  322.         a = array.array("f", data)
  323.         if self.prefix != native_prefix:
  324.             a.byteswap()
  325.         return tuple(a)
  326.     load_dispatch[11] = (4, load_float)
  327.  
  328.     def load_double(self, data):
  329.         a = array.array("d", data)
  330.         if self.prefix != native_prefix:
  331.             a.byteswap()
  332.         return tuple(a)
  333.     load_dispatch[12] = (8, load_double)
  334.  
  335.     def load_undefined(self, data):
  336.         # Untyped data
  337.         return data
  338.     load_dispatch[7] = (1, load_undefined)
  339.  
  340.     def load(self, fp):
  341.         # load tag dictionary
  342.  
  343.         self.reset()
  344.  
  345.         i16 = self.i16
  346.         i32 = self.i32
  347.  
  348.         for i in range(i16(fp.read(2))):
  349.  
  350.             ifd = fp.read(12)
  351.  
  352.             tag, typ = i16(ifd), i16(ifd, 2)
  353.  
  354.             if Image.DEBUG:
  355.                 import TiffTags
  356.                 tagname = TiffTags.TAGS.get(tag, "unknown")
  357.                 typname = TiffTags.TYPES.get(typ, "unknown")
  358.                 print "tag: %s (%d)" % (tagname, tag),
  359.                 print "- type: %s (%d)" % (typname, typ),
  360.  
  361.             try:
  362.                 dispatch = self.load_dispatch[typ]
  363.             except KeyError:
  364.                 if Image.DEBUG:
  365.                     print "- unsupported type", typ
  366.                 continue # ignore unsupported type
  367.  
  368.             size, handler = dispatch
  369.  
  370.             size = size * i32(ifd, 4)
  371.  
  372.             # Get and expand tag value
  373.             if size > 4:
  374.                 here = fp.tell()
  375.                 fp.seek(i32(ifd, 8))
  376.                 data = ImageFile._safe_read(fp, size)
  377.                 fp.seek(here)
  378.             else:
  379.                 data = ifd[8:8+size]
  380.  
  381.             if len(data) != size:
  382.                 raise IOError, "not enough data"
  383.  
  384.             self.tagdata[tag] = typ, data
  385.             self.tagtype[tag] = typ
  386.  
  387.             if Image.DEBUG:
  388.                 if tag in (COLORMAP, IPTC_NAA_CHUNK, PHOTOSHOP_CHUNK, ICCPROFILE, XMP):
  389.                     print "- value: <table: %d bytes>" % size
  390.                 else:
  391.                     print "- value:", self[tag]
  392.  
  393.         self.next = i32(fp.read(4))
  394.  
  395.     # save primitives
  396.  
  397.     def save(self, fp):
  398.  
  399.         o16 = self.o16
  400.         o32 = self.o32
  401.  
  402.         fp.write(o16(len(self.tags)))
  403.  
  404.         # always write in ascending tag order
  405.         tags = self.tags.items()
  406.         tags.sort()
  407.  
  408.         directory = []
  409.         append = directory.append
  410.  
  411.         offset = fp.tell() + len(self.tags) * 12 + 4
  412.  
  413.         stripoffsets = None
  414.  
  415.         # pass 1: convert tags to binary format
  416.         for tag, value in tags:
  417.  
  418.             typ = None
  419.  
  420.             if self.tagtype.has_key(tag):
  421.                 typ = self.tagtype[tag]
  422.  
  423.             if typ == 1:
  424.                 # byte data
  425.                 data = value = string.join(map(chr, value), "")
  426.             elif typ == 7:
  427.                 # untyped data
  428.                 data = value = string.join(value, "")
  429.             elif type(value[0]) is type(""):
  430.                 # string data
  431.                 typ = 2
  432.                 data = value = string.join(value, "\0") + "\0"
  433.             else:
  434.                 # integer data
  435.                 if tag == STRIPOFFSETS:
  436.                     stripoffsets = len(directory)
  437.                     typ = 4 # to avoid catch-22
  438.                 elif tag in (X_RESOLUTION, Y_RESOLUTION):
  439.                     # identify rational data fields
  440.                     typ = 5
  441.                 elif not typ:
  442.                     typ = 3
  443.                     for v in value:
  444.                         if v >= 65536:
  445.                             typ = 4
  446.                 if typ == 3:
  447.                     data = string.join(map(o16, value), "")
  448.                 else:
  449.                     data = string.join(map(o32, value), "")
  450.  
  451.             if Image.DEBUG:
  452.                 import TiffTags
  453.                 tagname = TiffTags.TAGS.get(tag, "unknown")
  454.                 typname = TiffTags.TYPES.get(typ, "unknown")
  455.                 print "save: %s (%d)" % (tagname, tag),
  456.                 print "- type: %s (%d)" % (typname, typ),
  457.                 if tag in (COLORMAP, IPTC_NAA_CHUNK, PHOTOSHOP_CHUNK, ICCPROFILE, XMP):
  458.                     size = len(data)
  459.                     print "- value: <table: %d bytes>" % size
  460.                 else:
  461.                     print "- value:", value
  462.  
  463.             # figure out if data fits into the directory
  464.             if len(data) == 4:
  465.                 append((tag, typ, len(value), data, ""))
  466.             elif len(data) < 4:
  467.                 append((tag, typ, len(value), data + (4-len(data))*"\0", ""))
  468.             else:
  469.                 count = len(value)
  470.                 if typ == 5:
  471.                     count = count / 2        # adjust for rational data field
  472.                 append((tag, typ, count, o32(offset), data))
  473.                 offset = offset + len(data)
  474.                 if offset & 1:
  475.                     offset = offset + 1 # word padding
  476.  
  477.         # update strip offset data to point beyond auxiliary data
  478.         if stripoffsets is not None:
  479.             tag, typ, count, value, data = directory[stripoffsets]
  480.             assert not data, "multistrip support not yet implemented"
  481.             value = o32(self.i32(value) + offset)
  482.             directory[stripoffsets] = tag, typ, count, value, data
  483.  
  484.         # pass 2: write directory to file
  485.         for tag, typ, count, value, data in directory:
  486.             if Image.DEBUG > 1:
  487.                 print tag, typ, count, repr(value), repr(data)
  488.             fp.write(o16(tag) + o16(typ) + o32(count) + value)
  489.  
  490.         # -- overwrite here for multi-page --
  491.         fp.write("\0\0\0\0") # end of directory
  492.  
  493.         # pass 3: write auxiliary data to file
  494.         for tag, typ, count, value, data in directory:
  495.             fp.write(data)
  496.             if len(data) & 1:
  497.                 fp.write("\0")
  498.  
  499.         return offset
  500.  
  501. ##
  502. # Image plugin for TIFF files.
  503.  
  504. class TiffImageFile(ImageFile.ImageFile):
  505.  
  506.     format = "TIFF"
  507.     format_description = "Adobe TIFF"
  508.  
  509.     def _open(self):
  510.         "Open the first image in a TIFF file"
  511.  
  512.         # Header
  513.         ifh = self.fp.read(8)
  514.  
  515.         if ifh[:4] not in PREFIXES:
  516.             raise SyntaxError, "not a TIFF file"
  517.  
  518.         # image file directory (tag dictionary)
  519.         self.tag = self.ifd = ImageFileDirectory(ifh[:2])
  520.  
  521.         # setup frame pointers
  522.         self.__first = self.__next = self.ifd.i32(ifh, 4)
  523.         self.__frame = -1
  524.         self.__fp = self.fp
  525.  
  526.         # and load the first frame
  527.         self._seek(0)
  528.  
  529.     def seek(self, frame):
  530.         "Select a given frame as current image"
  531.  
  532.         if frame < 0:
  533.             frame = 0
  534.         self._seek(frame)
  535.  
  536.     def tell(self):
  537.         "Return the current frame number"
  538.  
  539.         return self._tell()
  540.  
  541.     def _seek(self, frame):
  542.  
  543.         self.fp = self.__fp
  544.         if frame < self.__frame:
  545.             # rewind file
  546.             self.__frame = -1
  547.             self.__next = self.__first
  548.         while self.__frame < frame:
  549.             if not self.__next:
  550.                 raise EOFError, "no more images in TIFF file"
  551.             self.fp.seek(self.__next)
  552.             self.tag.load(self.fp)
  553.             self.__next = self.tag.next
  554.             self.__frame = self.__frame + 1
  555.         self._setup()
  556.  
  557.     def _tell(self):
  558.  
  559.         return self.__frame
  560.  
  561.     def _decoder(self, rawmode, layer):
  562.         "Setup decoder contexts"
  563.  
  564.         args = None
  565.         if rawmode == "RGB" and self._planar_configuration == 2:
  566.             rawmode = rawmode[layer]
  567.         compression = self._compression
  568.         if compression == "raw":
  569.             args = (rawmode, 0, 1)
  570.         elif compression == "jpeg":
  571.             args = rawmode, ""
  572.             if self.tag.has_key(JPEGTABLES):
  573.                 # Hack to handle abbreviated JPEG headers
  574.                 self.tile_prefix = self.tag[JPEGTABLES]
  575.         elif compression == "packbits":
  576.             args = rawmode
  577.         elif compression == "tiff_lzw":
  578.             args = rawmode
  579.             if self.tag.has_key(317):
  580.                 # Section 14: Differencing Predictor
  581.                 self.decoderconfig = (self.tag[PREDICTOR][0],)
  582.  
  583.         if self.tag.has_key(ICCPROFILE):
  584.             self.info['icc_profile'] = self.tag[ICCPROFILE]
  585.  
  586.         return args
  587.  
  588.     def _setup(self):
  589.         "Setup this image object based on current tags"
  590.  
  591.         if self.tag.has_key(0xBC01):
  592.             raise IOError, "Windows Media Photo files not yet supported"
  593.  
  594.         getscalar = self.tag.getscalar
  595.  
  596.         # extract relevant tags
  597.         self._compression = COMPRESSION_INFO[getscalar(COMPRESSION, 1)]
  598.         self._planar_configuration = getscalar(PLANAR_CONFIGURATION, 1)
  599.  
  600.         # photometric is a required tag, but not everyone is reading
  601.         # the specification
  602.         photo = getscalar(PHOTOMETRIC_INTERPRETATION, 0)
  603.  
  604.         fillorder = getscalar(FILLORDER, 1)
  605.  
  606.         if Image.DEBUG:
  607.             print "*** Summary ***"
  608.             print "- compression:", self._compression
  609.             print "- photometric_interpretation:", photo
  610.             print "- planar_configuration:", self._planar_configuration
  611.             print "- fill_order:", fillorder
  612.  
  613.         # size
  614.         xsize = getscalar(IMAGEWIDTH)
  615.         ysize = getscalar(IMAGELENGTH)
  616.         self.size = xsize, ysize
  617.  
  618.         if Image.DEBUG:
  619.             print "- size:", self.size
  620.  
  621.         format = getscalar(SAMPLEFORMAT, 1)
  622.  
  623.         # mode: check photometric interpretation and bits per pixel
  624.         key = (
  625.             self.tag.prefix, photo, format, fillorder,
  626.             self.tag.get(BITSPERSAMPLE, (1,)),
  627.             self.tag.get(EXTRASAMPLES, ())
  628.             )
  629.         if Image.DEBUG:
  630.             print "format key:", key
  631.         try:
  632.             self.mode, rawmode = OPEN_INFO[key]
  633.         except KeyError:
  634.             if Image.DEBUG:
  635.                 print "- unsupported format"
  636.             raise SyntaxError, "unknown pixel mode"
  637.  
  638.         if Image.DEBUG:
  639.             print "- raw mode:", rawmode
  640.             print "- pil mode:", self.mode
  641.  
  642.         self.info["compression"] = self._compression
  643.  
  644.         xres = getscalar(X_RESOLUTION, (1, 1))
  645.         yres = getscalar(Y_RESOLUTION, (1, 1))
  646.  
  647.         if xres and yres:
  648.             xres = xres[0] / (xres[1] or 1)
  649.             yres = yres[0] / (yres[1] or 1)
  650.             resunit = getscalar(RESOLUTION_UNIT, 1)
  651.             if resunit == 2: # dots per inch
  652.                 self.info["dpi"] = xres, yres
  653.             elif resunit == 3: # dots per centimeter. convert to dpi
  654.                 self.info["dpi"] = xres * 2.54, yres * 2.54
  655.             else: # No absolute unit of measurement
  656.                 self.info["resolution"] = xres, yres
  657.  
  658.         # build tile descriptors
  659.         x = y = l = 0
  660.         self.tile = []
  661.         if self.tag.has_key(STRIPOFFSETS):
  662.             # striped image
  663.             h = getscalar(ROWSPERSTRIP, ysize)
  664.             w = self.size[0]
  665.             a = None
  666.             for o in self.tag[STRIPOFFSETS]:
  667.                 if not a:
  668.                     a = self._decoder(rawmode, l)
  669.                 self.tile.append(
  670.                     (self._compression,
  671.                     (0, min(y, ysize), w, min(y+h, ysize)),
  672.                     o, a))
  673.                 y = y + h
  674.                 if y >= self.size[1]:
  675.                     x = y = 0
  676.                     l = l + 1
  677.                     a = None
  678.         elif self.tag.has_key(TILEOFFSETS):
  679.             # tiled image
  680.             w = getscalar(322)
  681.             h = getscalar(323)
  682.             a = None
  683.             for o in self.tag[TILEOFFSETS]:
  684.                 if not a:
  685.                     a = self._decoder(rawmode, l)
  686.                 # FIXME: this doesn't work if the image size
  687.                 # is not a multiple of the tile size...
  688.                 self.tile.append(
  689.                     (self._compression,
  690.                     (x, y, x+w, y+h),
  691.                     o, a))
  692.                 x = x + w
  693.                 if x >= self.size[0]:
  694.                     x, y = 0, y + h
  695.                     if y >= self.size[1]:
  696.                         x = y = 0
  697.                         l = l + 1
  698.                         a = None
  699.         else:
  700.             if Image.DEBUG:
  701.                 print "- unsupported data organization"
  702.             raise SyntaxError("unknown data organization")
  703.  
  704.         # fixup palette descriptor
  705.  
  706.         if self.mode == "P":
  707.             palette = map(lambda a: chr(a / 256), self.tag[COLORMAP])
  708.             self.palette = ImagePalette.raw("RGB;L", string.join(palette, ""))
  709. #
  710. # --------------------------------------------------------------------
  711. # Write TIFF files
  712.  
  713. # little endian is default except for image modes with explict big endian byte-order
  714.  
  715. SAVE_INFO = {
  716.     # mode => rawmode, byteorder, photometrics, sampleformat, bitspersample, extra
  717.     "1": ("1", II, 1, 1, (1,), None),
  718.     "L": ("L", II, 1, 1, (8,), None),
  719.     "LA": ("LA", II, 1, 1, (8,8), 2),
  720.     "P": ("P", II, 3, 1, (8,), None),
  721.     "PA": ("PA", II, 3, 1, (8,8), 2),
  722.     "I": ("I;32S", II, 1, 2, (32,), None),
  723.     "I;16": ("I;16", II, 1, 1, (16,), None),
  724.     "I;16S": ("I;16S", II, 1, 2, (16,), None),
  725.     "F": ("F;32F", II, 1, 3, (32,), None),
  726.     "RGB": ("RGB", II, 2, 1, (8,8,8), None),
  727.     "RGBX": ("RGBX", II, 2, 1, (8,8,8,8), 0),
  728.     "RGBA": ("RGBA", II, 2, 1, (8,8,8,8), 2),
  729.     "CMYK": ("CMYK", II, 5, 1, (8,8,8,8), None),
  730.     "YCbCr": ("YCbCr", II, 6, 1, (8,8,8), None),
  731.     "LAB": ("LAB", II, 8, 1, (8,8,8), None),
  732.  
  733.     "I;32BS": ("I;32BS", MM, 1, 2, (32,), None),
  734.     "I;16B": ("I;16B", MM, 1, 1, (16,), None),
  735.     "I;16BS": ("I;16BS", MM, 1, 2, (16,), None),
  736.     "F;32BF": ("F;32BF", MM, 1, 3, (32,), None),
  737. }
  738.  
  739. def _cvt_res(value):
  740.     # convert value to TIFF rational number -- (numerator, denominator)
  741.     if type(value) in (type([]), type(())):
  742.         assert(len(value) % 2 == 0)
  743.         return value
  744.     if type(value) == type(1):
  745.         return (value, 1)
  746.     value = float(value)
  747.     return (int(value * 65536), 65536)
  748.  
  749. def _save(im, fp, filename):
  750.  
  751.     try:
  752.         rawmode, prefix, photo, format, bits, extra = SAVE_INFO[im.mode]
  753.     except KeyError:
  754.         raise IOError, "cannot write mode %s as TIFF" % im.mode
  755.  
  756.     ifd = ImageFileDirectory(prefix)
  757.  
  758.     # -- multi-page -- skip TIFF header on subsequent pages
  759.     if fp.tell() == 0:
  760.         # tiff header (write via IFD to get everything right)
  761.         # PIL always starts the first IFD at offset 8
  762.         fp.write(ifd.prefix + ifd.o16(42) + ifd.o32(8))
  763.  
  764.     ifd[IMAGEWIDTH] = im.size[0]
  765.     ifd[IMAGELENGTH] = im.size[1]
  766.  
  767.     # additions written by Greg Couch, gregc@cgl.ucsf.edu
  768.     # inspired by image-sig posting from Kevin Cazabon, kcazabon@home.com
  769.     if hasattr(im, 'tag'):
  770.         # preserve tags from original TIFF image file
  771.         for key in (RESOLUTION_UNIT, X_RESOLUTION, Y_RESOLUTION):
  772.             if im.tag.tagdata.has_key(key):
  773.                 ifd[key] = im.tag.tagdata.get(key)
  774.         # preserve some more tags from original TIFF image file
  775.         # -- 2008-06-06 Florian Hoech
  776.         ifd.tagtype = im.tag.tagtype
  777.         for key in (IPTC_NAA_CHUNK, PHOTOSHOP_CHUNK, XMP):
  778.             if im.tag.has_key(key):
  779.                 ifd[key] = im.tag[key]
  780.         # preserve ICC profile (should also work when saving other formats
  781.         # which support profiles as TIFF) -- 2008-06-06 Florian Hoech
  782.         if im.info.has_key("icc_profile"):
  783.             ifd[ICCPROFILE] = im.info["icc_profile"]
  784.     if im.encoderinfo.has_key("description"):
  785.         ifd[IMAGEDESCRIPTION] = im.encoderinfo["description"]
  786.     if im.encoderinfo.has_key("resolution"):
  787.         ifd[X_RESOLUTION] = ifd[Y_RESOLUTION] \
  788.                                 = _cvt_res(im.encoderinfo["resolution"])
  789.     if im.encoderinfo.has_key("x resolution"):
  790.         ifd[X_RESOLUTION] = _cvt_res(im.encoderinfo["x resolution"])
  791.     if im.encoderinfo.has_key("y resolution"):
  792.         ifd[Y_RESOLUTION] = _cvt_res(im.encoderinfo["y resolution"])
  793.     if im.encoderinfo.has_key("resolution unit"):
  794.         unit = im.encoderinfo["resolution unit"]
  795.         if unit == "inch":
  796.             ifd[RESOLUTION_UNIT] = 2
  797.         elif unit == "cm" or unit == "centimeter":
  798.             ifd[RESOLUTION_UNIT] = 3
  799.         else:
  800.             ifd[RESOLUTION_UNIT] = 1
  801.     if im.encoderinfo.has_key("software"):
  802.         ifd[SOFTWARE] = im.encoderinfo["software"]
  803.     if im.encoderinfo.has_key("date time"):
  804.         ifd[DATE_TIME] = im.encoderinfo["date time"]
  805.     if im.encoderinfo.has_key("artist"):
  806.         ifd[ARTIST] = im.encoderinfo["artist"]
  807.     if im.encoderinfo.has_key("copyright"):
  808.         ifd[COPYRIGHT] = im.encoderinfo["copyright"]
  809.  
  810.     dpi = im.encoderinfo.get("dpi")
  811.     if dpi:
  812.         ifd[RESOLUTION_UNIT] = 2
  813.         ifd[X_RESOLUTION] = _cvt_res(dpi[0])
  814.         ifd[Y_RESOLUTION] = _cvt_res(dpi[1])
  815.  
  816.     if bits != (1,):
  817.         ifd[BITSPERSAMPLE] = bits
  818.         if len(bits) != 1:
  819.             ifd[SAMPLESPERPIXEL] = len(bits)
  820.     if extra is not None:
  821.         ifd[EXTRASAMPLES] = extra
  822.     if format != 1:
  823.         ifd[SAMPLEFORMAT] = format
  824.  
  825.     ifd[PHOTOMETRIC_INTERPRETATION] = photo
  826.  
  827.     if im.mode == "P":
  828.         lut = im.im.getpalette("RGB", "RGB;L")
  829.         ifd[COLORMAP] = tuple(map(lambda v: ord(v) * 256, lut))
  830.  
  831.     # data orientation
  832.     stride = len(bits) * ((im.size[0]*bits[0]+7)/8)
  833.     ifd[ROWSPERSTRIP] = im.size[1]
  834.     ifd[STRIPBYTECOUNTS] = stride * im.size[1]
  835.     ifd[STRIPOFFSETS] = 0 # this is adjusted by IFD writer
  836.     ifd[COMPRESSION] = 1 # no compression
  837.  
  838.     offset = ifd.save(fp)
  839.  
  840.     ImageFile._save(im, fp, [
  841.         ("raw", (0,0)+im.size, offset, (rawmode, stride, 1))
  842.         ])
  843.  
  844.  
  845.     # -- helper for multi-page save --
  846.     if im.encoderinfo.has_key("_debug_multipage"):
  847.         #just to access o32 and o16 (using correct byte order)
  848.         im._debug_multipage = ifd
  849.  
  850. #
  851. # --------------------------------------------------------------------
  852. # Register
  853.  
  854. Image.register_open("TIFF", TiffImageFile, _accept)
  855. Image.register_save("TIFF", _save)
  856.  
  857. Image.register_extension("TIFF", ".tif")
  858. Image.register_extension("TIFF", ".tiff")
  859.  
  860. Image.register_mime("TIFF", "image/tiff")
  861.